
#include "WTSXSipService/SipSessionMgr.hpp"
#include "WTSXSipService/SipTranSession.hpp"
#include "WTSXSipService/SipDlgSessionBase.hpp"
#include "WTSXSipService/SipInviteSession.hpp"

#include "WTResipDll/SipDebugInfo.hpp"
#include "WTResipDll/SipWtsipUtils.hpp"

#include <boost/thread/locks.hpp>

namespace wtsxsip{

CSipSessionMgr::CSipSessionMgr(void)
{
}

CSipSessionMgr::~CSipSessionMgr(void)
{
}


CSipTranSession* CSipSessionMgr::createSession(wtsip::ISipClnTransaction& clnTran, wtsip::CapSipMessage request)
{
    if (!request.get() || !request->isRequest()){
        ERROR_LINE("Expected request.");
        return NULL;
    }
    uint32_t id = m_handleMgr.generateHandle();
    if (CSipHandleMgr::INVALID_HANDLE == id){
        ERROR_LINE("Generate handle failed.");
        return NULL;
    }
    CSipTranSession* pTranSession = NULL;
    pTranSession = new CSipTranSession(*this, id, clnTran, request);
    if (!insertSession(pTranSession))
    {
        if (pTranSession)
            delete pTranSession;

        m_handleMgr.recycleHandle(id);
        pTranSession = NULL;
    }
    return pTranSession;
}


CSipTranSession* CSipSessionMgr::createSession(wtsip::ISipSrvTransaction& srvtran, wtsip::CapSipMessage request)
{
    if (!request.get() || !request->isRequest()){
        ERROR_LINE("Expected request.");
        return NULL;
    }
    uint32_t id = m_handleMgr.generateHandle();
    if (CSipHandleMgr::INVALID_HANDLE == id){
        ERROR_LINE("Generate handle failed.");
        return NULL;
    }
    CSipTranSession* pTranSession = NULL;
    pTranSession = new CSipTranSession(*this, id, srvtran, request);
    if (!insertSession(pTranSession))
    {
        if (pTranSession)
            delete pTranSession;

        m_handleMgr.recycleHandle(id);
        pTranSession = NULL;
    }
    return pTranSession;
}


CSipDlgSessionBase* CSipSessionMgr::createDlgSession(wtsip::ISipDialogBase& dlg, 
                                                     const wtsip::SUri& tar, 
                                                     const ISipDlgSessionBase::EDlgType type)
{
    uint32_t id = m_handleMgr.generateHandle();
    if (CSipHandleMgr::INVALID_HANDLE == id){
        ERROR_LINE("Generate handle failed.");
        return NULL;
    }

    CSipDlgSessionBase* pDlgSession = NULL;
    if (ISipDlgSessionBase::Invite == type)
    {
        pDlgSession = new CSipInviteSession(*this, id, dlg, tar);
    } else {
        pDlgSession = new CSipDlgSessionBase(*this, id, dlg, tar);
    }
    if (!insertSession(pDlgSession))
    {
        if (pDlgSession)
            delete pDlgSession;

        m_handleMgr.recycleHandle(id);
        pDlgSession = NULL;
    }
    return pDlgSession;
}


CSipDlgSessionBase* CSipSessionMgr::createDlgSession(wtsip::ISipDialogBase& dlg, 
                                                     wtsip::ISipSrvTransaction& srvtran, 
                                                     wtsip::CapSipMessage request, 
                                                     ISipTranSession*& pTran)
{
    if (!request.get() || !request->isRequest()){
        ERROR_LINE("Expected request.");
        return NULL;
    }
    wtsip::SUri target;
    if (!wtsip::CSipWtsipUntils::tran2SUri(target, request->header(resip::h_RequestLine).uri())){
        ERROR_LINE("Tran to SUri failed.");
        return NULL;
    }
    pTran = createSession(srvtran, request);
    if (!pTran){
        ERROR_LINE("Create tran session failed.");
        return NULL;
    }
    uint32_t id = m_handleMgr.generateHandle();
    if (CSipHandleMgr::INVALID_HANDLE == id){
        ERROR_LINE("Generate handle failed.");
        return NULL;
    }

    CSipDlgSessionBase* pDlgSession = NULL;
    if (resip::INVITE == request->method())
    {
        pDlgSession = new CSipInviteSession(*this, id, dlg, target, *pTran);
    } else {
        pDlgSession = new CSipDlgSessionBase(*this, id, dlg, target, *pTran);
    }
    
    if (!insertSession(pDlgSession))
    {
        if (pDlgSession)
            delete pDlgSession;

        m_handleMgr.recycleHandle(id);
        pDlgSession = NULL;
    }
    return pDlgSession;
}


bool CSipSessionMgr::insertSession(CSipSessionBase* session)
{
    if (!session){
        ERROR_LINE("Can't insert empty.");
        return false;
    }
    uint32_t sId = session->getID();
    boost::unique_lock<boost::shared_mutex> wLock(m_SessionsMutex);

    std::pair<std::map<uint32_t, CSipSessionBase*>::iterator, bool> ret;
    ret = m_sessions.insert(std::make_pair(sId, session));
    if (!ret.second){
        ERROR_LINE("Insert session failed.");
        return false;
    }

    return true;
}


CSipSessionBase* CSipSessionMgr::matchSession(const uint32_t sid) const
{
    if (CSipHandleMgr::INVALID_HANDLE == sid)
    {
        ERROR_LINE("Invalid ID.");
        return NULL;
    }

    boost::shared_lock<boost::shared_mutex> rLock(m_SessionsMutex);

    CSipSessionBase* sn = NULL;
    std::map<uint32_t, CSipSessionBase*>::const_iterator it;
    it = m_sessions.find(sid);
    if (it != m_sessions.end()){
        sn = it->second;
    }
    return sn;
}


bool CSipSessionMgr::destroySession(const uint32_t sid)
{
    if (CSipHandleMgr::INVALID_HANDLE == sid){
        ERROR_LINE("Invalid ID.");
        return false;
    }

    boost::unique_lock<boost::shared_mutex> wLock(m_SessionsMutex);

    CSipSessionBase* sn = NULL;
    std::map<uint32_t, CSipSessionBase*>::iterator it;
    it = m_sessions.find(sid);
    if (it != m_sessions.end()){
        sn = it->second;
    }
    
    if (it != m_sessions.end()){
        if (!sn){
            ERROR_LINE("There is fake session.");
        } else {
            m_handleMgr.recycleHandle(sn->getID());
            delete sn;
        }
        m_sessions.erase(it);
    }
    return true;
}



}//namespace

